﻿#region Copyright 2011 Mike Goatly
// This source is subject to the the MIT License (MIT)
// All rights reserved.
#endregion

namespace Lifti.Tests.Persistence.PageManagerTests.Transactional
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Transactions;

    using Lifti.Persistence;

    using Microsoft.VisualStudio.TestTools.UnitTesting;

    using Moq;

    /// <summary>
    /// Tests for the committing of a transaction after using a <see cref="TransactionalPageManager&lt;TItem&gt;"/>
    /// </summary>
    [TestClass]
    public class CommittingTransaction : TransactionalPageManagerTestBase
    {
        /// <summary>
        /// When the transaction is committed, any modified page bodies should be
        /// written to the backing store.
        /// </summary>
        [TestMethod]
        public void ShouldWriteChangedDataPageBodiesToBackingFile()
        {
            using (var scope = new TransactionScope())
            {
                var page = this.PageManager.GetPage(0);
                this.PageManager.SavePage(page);

                scope.Complete();
            }

            this.DataFileManager.VerifyPageManagerHeaderWritten(Times.Never());
            this.DataFileManager.VerifyPageWritten(0, Times.Exactly(1));
        }

        /// <summary>
        /// When the transaction is committed, any modified page headers should be
        /// written to the backing store.
        /// </summary>
        [TestMethod]
        public void ShouldWriteChangedPageHeadersToBackingFile()
        {
            using (var scope = new TransactionScope())
            {
                var page = (IndexNodeDataPage)this.PageManager.GetPage(2);

                // Remove all entries and save the page to force its invalidation. This will affect the page links around it
                page.RemoveEntry(e => true);
                this.PageManager.SavePage(page);

                scope.Complete();
            }

            this.DataFileManager.VerifyPageManagerHeaderWritten(Times.Never());
            this.DataFileManager.VerifyPageHeaderWritten(0, Times.Exactly(1));
            this.DataFileManager.VerifyPageHeaderWritten(2, Times.Exactly(1));
            this.DataFileManager.VerifyPageHeaderWritten(3, Times.Exactly(1));
        }

        /// <summary>
        /// When the transaction is committed, the page manager headers should be
        /// written to the backing store if they have been affected.
        /// </summary>
        [TestMethod]
        public void ShouldWriteChangedPageManagerHeaderToBackingFile()
        {
            using (var scope = new TransactionScope())
            {
                var page = (IndexNodeDataPage)this.PageManager.GetPage(0);

                // Remove all entries and save the page to force its invalidation. This will affect the page links around it
                page.RemoveEntry(e => true);
                this.PageManager.SavePage(page);

                scope.Complete();
            }

            this.DataFileManager.VerifyPageManagerHeaderWritten(Times.Exactly(1));
            this.DataFileManager.VerifyPageHeaderWritten(0, Times.Exactly(1));
            this.DataFileManager.VerifyPageHeaderWritten(2, Times.Exactly(1));
            this.DataFileManager.VerifyPageHeaderWritten(3, Times.Exactly(0));
        }
    }
}
